package com.yc.cloud.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.admin.dto.request.HwDeviceGroupSaveReqDto;
import com.yc.cloud.admin.service.AlgStrategyService;
import com.yc.cloud.admin.service.HwDeviceGroupService;
import com.yc.cloud.admin.service.HwDeviceService;
import com.yc.cloud.admin.vo.AlgStrategyVo;
import com.yc.cloud.admin.vo.HwDeviceGroupStrategyVo;
import com.yc.cloud.admin.vo.HwDeviceGroupVo;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.entity.AlgStrategy;
import com.yc.cloud.entity.HwDevice;
import com.yc.cloud.entity.HwDeviceGroup;
import com.yc.cloud.entity.HwDeviceGroupStrategy;
import com.yc.cloud.entity.UmsAdmin;
import com.yc.cloud.mapper.HwDeviceGroupMapper;
import com.yc.cloud.mapper.HwDeviceGroupStrategyMapper;
import com.yc.cloud.mapper.UmsAdminMapper;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class HwDeviceGroupServiceImpl extends ServiceImpl<HwDeviceGroupMapper, HwDeviceGroup>
        implements HwDeviceGroupService {

    @Autowired
    private HwDeviceService hwDeviceService;

    @Autowired
    private AlgStrategyService algStrategyService;

    @Autowired
    private UmsAdminMapper umsAdminMapper;

    @Autowired
    private HwDeviceGroupStrategyMapper hwDeviceGroupStrategyMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateGroupDevices(Long groupId, List<Long> deviceIds) {
        // 1. 检查设备组是否存在
        HwDeviceGroup group = this.getById(groupId);
        if (group == null) {
            Asserts.fail("指定的设备组不存在");
        }

        // 2. 解绑该分组下的所有设备 (将groupId设为null)
        hwDeviceService.unbindDevicesFromGroup(groupId);

        // 3. 绑定新的设备列表
        if (CollUtil.isNotEmpty(deviceIds)) {
            hwDeviceService.bindDevicesToGroup(groupId, deviceIds);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(HwDeviceGroupSaveReqDto saveReqDto) {
        // 检查分组名称是否已存在
        long count = this.count(new QueryWrapper<HwDeviceGroup>().eq(HwDeviceGroup.Name, saveReqDto.getName()));
        if (count > 0) {
            Asserts.fail("已存在同名的设备分组");
        }
        HwDeviceGroup hwDeviceGroup = new HwDeviceGroup();
        BeanUtils.copyProperties(saveReqDto, hwDeviceGroup);
        return this.save(hwDeviceGroup);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Long id, HwDeviceGroupSaveReqDto saveReqDto) {
        HwDeviceGroup hwDeviceGroup = this.getById(id);
        if (hwDeviceGroup == null) {
            Asserts.fail("设备组不存在");
        }
        BeanUtils.copyProperties(saveReqDto, hwDeviceGroup);
        hwDeviceGroup.setId(id);
        return this.updateById(hwDeviceGroup);
    }

    @Override
    public CommonPage<HwDeviceGroupVo> list(BasePageReqDTO pageReqDTO) {
        Page<HwDeviceGroup> page = new Page<>(pageReqDTO.getPageNum(), pageReqDTO.getPageSize());
        IPage<HwDeviceGroup> pageResult = this.page(page, new QueryWrapper<>());
        // 直接转换，将查询逻辑放入 convertToVo 中
        return CommonPage.restPage(pageResult.convert(this::convertToVo));
    }

    @Override
    public HwDeviceGroupVo getVOById(Long id) {
        return convertToVo(this.getById(id));
    }

    @Override
    public List<HwDeviceGroupVo> convertToVoList(List<HwDeviceGroup> entityList) {
        if (CollUtil.isEmpty(entityList)) {
            return CollUtil.newArrayList();
        }
        return entityList.stream().map(this::convertToVo).collect(Collectors.toList());
    }

    private HwDeviceGroupVo convertToVo(HwDeviceGroup entity) {
        if (entity == null) {
            return null;
        }
        HwDeviceGroupVo vo = new HwDeviceGroupVo();
        BeanUtils.copyProperties(entity, vo);

        // 为每个分组查询其设备数量 (N+1 查询)
        long deviceCount = hwDeviceService.count(new QueryWrapper<HwDevice>().eq(HwDevice.GroupId, entity.getId()));
        vo.setDeviceCount(deviceCount);

        // 为每个分组查询其策略数量 (N+1 查询),后续在优化
        long strategyCount = hwDeviceGroupStrategyMapper.selectCount(new QueryWrapper<HwDeviceGroupStrategy>().eq(HwDeviceGroupStrategy.GroupId, entity.getId()));
        vo.setStrategyCount(strategyCount);
        
        // 查询创建者名称
        UmsAdmin user = umsAdminMapper.selectById(entity.getCreateBy());
        if (user != null) {
            vo.setCreateName(user.getTrueName());
        }
        return vo;
    }

    @Override
    public HwDeviceGroup get(Long id) {
        return this.getById(id);
    }

    @Override
    public boolean delete(Long id) {
        // 检查分组下是否还有设备
        long deviceCount = hwDeviceService.count(new QueryWrapper<HwDevice>().eq(HwDevice.GroupId, id));
        if (deviceCount > 0) {
            Asserts.fail("该设备分组下仍有关联设备，禁止删除");
        }
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateGroupStrategies(Long groupId, List<Long> strategyIds) {
        // 1. 检查设备组是否存在
        HwDeviceGroup group = this.getById(groupId);
        if (group == null) {
            Asserts.fail("指定的设备组不存在");
        }

        // 2. 删除该设备组与所有策略的关联关系
        hwDeviceGroupStrategyMapper.delete(
                new QueryWrapper<HwDeviceGroupStrategy>().eq(HwDeviceGroupStrategy.GroupId, groupId));

        // 3. 建立新的关联关系
        if (CollUtil.isNotEmpty(strategyIds)) {
            for (Long strategyId : strategyIds) {
                HwDeviceGroupStrategy relation = new HwDeviceGroupStrategy();
                relation.setGroupId(groupId);
                relation.setStrategyId(strategyId);
                hwDeviceGroupStrategyMapper.insert(relation);
            }
        }

        return true;
    }

    @Override
    public List<HwDeviceGroupStrategyVo> getGroupStrategies(Long groupId) {
        // 1. 检查设备组是否存在
        HwDeviceGroup group = this.getById(groupId);
        if (group == null) {
            Asserts.fail("指定的设备组不存在");
        }

        // 2. 获取当前设备组已绑定的所有策略ID
        List<Long> boundStrategyIds = hwDeviceGroupStrategyMapper.selectStrategyIdsByGroupId(groupId);

        // 3. 获取系统中的所有策略
        // 注意：这里假设系统中的策略数量不会非常巨大。如果策略数量可能上千上万，
        // 则不应一次性全部加载，需要改为分页加载。
        List<AlgStrategy> allStrategies = algStrategyService.list();
        if (CollUtil.isEmpty(allStrategies)) {
            return CollUtil.newArrayList();
        }

        List<AlgStrategyVo> allStrategyVos = algStrategyService.convertToVoList(allStrategies);

        // 4. 组装结果
        return allStrategyVos.stream().map(strategyVo -> {
            HwDeviceGroupStrategyVo vo = new HwDeviceGroupStrategyVo();
            BeanUtils.copyProperties(strategyVo, vo);
            // 检查当前策略ID是否存在于已绑定ID列表中
            vo.setBound(boundStrategyIds.contains(strategyVo.getId()));
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean refreshData() {
        // 刷新设备分组相关的缓存数据
        // 这里主要是让前端重新调用接口获取最新的统计信息
        // 比如设备数量统计、策略数量统计等
        return true;
    }
}